#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
模型17：单一销方单位同一天开具餐饮发票分析

主要功能：
1. 筛选业务类型为0015的记录
2. 分析同一天同一销方单位的发票情况
3. 根据条件判断一级/二级风险
   - 销方单位名称包含"酒店"为二级
   - 发票含税金额在700-800或980-999之间为二级
   - 两张发票且金额都小于1000，且差值小于100为二级
"""

import pandas as pd
from pathlib import Path

# 配置常量
DATA_DIR = Path("data")
OUTPUT_DIR = DATA_DIR / "alldata"  # 输出目录
EXPENSE_FILE = DATA_DIR / "费用报销票据信息.xlsx"
OUTPUT_FILE = OUTPUT_DIR / "单一销方单位同一天开具餐饮发票分析结果.xlsx"

def load_data():
    """
    加载数据并进行基础处理
    
    Returns:
        DataFrame: 处理后的数据
    """
    # 确保输出目录存在
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    
    try:
        # 读取费用数据
        df = pd.read_excel(EXPENSE_FILE)
        
        # 先将业务类型转换为字符串，并保持4位数格式（补零）
        df['业务类型'] = df['业务类型'].astype(str).str.zfill(4)
        
        # 转换日期格式但保留原始格式
        df['开票日期_原始'] = df['开票日期'].copy()  # 保存原始格式
        df['开票日期'] = pd.to_datetime(df['开票日期']).dt.normalize()
        
        return df
    except Exception as e:
        print(f"读取数据时出错: {str(e)}")
        raise

def analyze_receipts(df):
    """
    分析发票数据
    
    Args:
        df: DataFrame 原始数据
        
    Returns:
        DataFrame: 分析结果
    """
    try:
        # 1. 筛选业务类型为0015的记录
        df_filtered = df[df['业务类型'].str.strip() == '0015'].copy()
        
        if df_filtered.empty:
            print("警告：没有找到业务类型为0015的记录")
            print("当前数据中的业务类型值：", df['业务类型'].unique())
            return pd.DataFrame()
        
        print(f"找到业务类型为0015的记录数：{len(df_filtered)}")
        
        # 2. 按开票日期和销方单位分组计算发票数量
        grouped = df_filtered.groupby(['开票日期', '销方单位'])['发票号码'].count().reset_index()
        grouped.columns = ['开票日期', '销方单位', '发票张数']
        
        # 3. 筛选发票张数大于1的记录
        multiple_receipts = grouped[grouped['发票张数'] > 1]
        
        if multiple_receipts.empty:
            print("警告：没有找到同一天同一销方单位开具的多张发票")
            return pd.DataFrame()
        
        # 4. 获取满足条件的发票详细信息
        result = pd.merge(df_filtered, multiple_receipts[['开票日期', '销方单位', '发票张数']], 
                         on=['开票日期', '销方单位'])
        
        if result.empty:
            print("警告：合并后没有符合条件的数据")
            return pd.DataFrame()
        
        # 5. 按组排序并计算风险等级
        result = result.sort_values(['开票日期', '销方单位', '发票含税金额'])
        
        # 初始化风险等级和发票金额等级列
        result['风险等级'] = '一级'
        result['发票金额等级'] = '一级'
        
        # 按组处理风险等级和发票金额等级
        for (date, vendor), group in result.groupby(['开票日期', '销方单位']):
            # 检查销方单位名称是否包含"酒店"
            if vendor and '酒店' in vendor:
                result.loc[group.index, '风险等级'] = '二级'
            
            # 处理每张发票的金额等级
            amounts = group['发票含税金额']
            for idx in group.index:
                amount = result.loc[idx, '发票含税金额']
                # 检查金额是否在特定范围内
                if (700 <= amount <= 800) or (980 <= amount <= 999):
                    result.loc[idx, '发票金额等级'] = '二级'
            
            # 检查两张发票的情况
            if len(group) == 2:
                if all(amounts < 1000):
                    diff = abs(amounts.iloc[1] - amounts.iloc[0])
                    if diff < 100:
                        result.loc[group.index, '发票金额等级'] = '二级'
        
        # 重命名发票张数列为同日发票张数
        result = result.rename(columns={'发票张数': '同日发票张数'})
        
        # 恢复原始开票日期格式
        result['开票日期'] = result['开票日期_原始']
        result = result.drop('开票日期_原始', axis=1)
        
        return result
        
    except Exception as e:
        print(f"分析数据时出错: {str(e)}")
        raise

def main(once = False):
    """主程序入口"""
    try:
        print("开始加载数据...")
        df = load_data()
        
        if df.empty:
            print("错误：输入数据为空")
            return False
            
        print("正在分析数据...")
        result = analyze_receipts(df)
        
        if result.empty:
            print("没有找到符合条件的数据")
            return False

        if once:
            return result

        # 保存结果
        with pd.ExcelWriter(OUTPUT_FILE, engine='openpyxl', mode='w') as writer:
            result.to_excel(writer, index=False)
            # 设置业务类型列为文本格式
            if '业务类型' in result.columns:
                worksheet = writer.sheets['Sheet1']
                for idx, col in enumerate(result.columns):
                    if col == '业务类型':
                        # 设置整列为文本格式
                        col_letter = chr(65 + idx)  # 将列索引转换为Excel列字母
                        worksheet.column_dimensions[col_letter].number_format = '@'
                        # 设置每个单元格为文本格式
                        for row in range(2, len(result) + 2):  # Excel是1-based，第一行是标题
                            cell = worksheet.cell(row=row, column=idx + 1)
                            cell.number_format = '@'  # 设置单元格格式为文本
                            # 确保单元格的值是字符串格式
                            cell.value = str(cell.value).zfill(4)
        
        print(f"\n分析完成，结果已保存至: {OUTPUT_FILE}")
        print(f"筛选出的记录数: {len(result)}")
        
        # 统计分析
        print("\n数据统计:")
        print(f"一级风险记录数: {len(result[result['风险等级'] == '一级'])}")
        print(f"二级风险记录数: {len(result[result['风险等级'] == '二级'])}")
        print(f"发票一级记录数: {len(result[result['发票金额等级'] == '一级'])}")
        print(f"发票二级记录数: {len(result[result['发票金额等级'] == '二级'])}")
        
        return True
        
    except Exception as e:
        print(f"处理过程中出现错误: {str(e)}")
        raise

if __name__ == "__main__":
    main() 